/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package luft27.propertytree;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;



/**
 *
 * @author amalikov
 */
public class PropertyNode {
	
	public PropertyNode(String name) {
		this(name, new PropertyValue(""));
	}

	public PropertyNode(String name, PropertyValue value) {
		this.name = name;
		this.value = value;
		children = new ConcurrentHashMap<>();
		listeners = new HashSet<>();
	}
	
	public PropertyValue get(String path) {
		return getNode(path).get();
	}
	
	public void set(String path, PropertyValue value) {
		getNode(path).set(value);
	}

	public synchronized PropertyValue get() {
		return value;
	}
	
	public synchronized void set(PropertyValue value) {
		this.value = value;
		for (PropertyChangedListener listener : listeners)
			listener.actionPerformed(value);
	}
	
	public String getName() {
		return name;
	}
	
	public int getIndex() {
		String[] ss = getName().split("[\\[\\]]");
		return ss.length > 1 ? Integer.parseInt(ss[1]) : 0;
	}
	
	public PropertyNode getNode(String path) {
		validatePath(path);
		
		int pos = path.indexOf(DELIMITER, 1);
		
		if (pos == -1) {
			String key = path.substring(1);
			if (!children.containsKey(key))
				children.put(key, new PropertyNode(key));

			return children.get(key);
		} else {
			String key = path.substring(1, pos);
			if (!children.containsKey(key))
				children.put(key, new PropertyNode(key));

			return children.get(key).getNode(path.substring(pos));
		}
	}

	public PropertyNode[] getChildren() {
		Collection<PropertyNode> coll = children.values();
		PropertyNode[] arr = new PropertyNode[coll.size()];
		return coll.toArray(arr);
	}

	public PropertyNode[] getChildren(String path) {
		return getNode(path).getChildren();
	}
	
	
	public synchronized void addListener(PropertyChangedListener listener) {
		listeners.add(listener);
	}

	public synchronized void removeListener(PropertyChangedListener listener) {
		listeners.remove(listener);
	}
	
	public void removeChildren() {
		children.clear();
	}
	
	private void validatePath(String path) {
		if (path == null || path.length() < 2 || path.charAt(0) != DELIMITER)
			throw new InvalidPathException();
	}
	
	private static final char DELIMITER = '/';
	private final String name;
	private PropertyValue value;
	private final Map<String, PropertyNode> children;
	private final Set<PropertyChangedListener> listeners;
}
